package org.lionsoul.ip2region;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @author koma <komazhang@foxmail.com>
 * @date 2019-12-26
 */
public class Ip2regionSearcher implements DisposableBean {

    public enum ALGORITHM {
        BTREE_SEARCH, BINARY_SEARCH, MEMORY_SEARCH
    }
    private ThreadLocal<String> threadLocal = new ThreadLocal<String>();
    private DbSearcher dbSearcher;

    public Ip2regionSearcher(DbSearcher dbSearcher) {
        this.dbSearcher = dbSearcher;
    }

    public synchronized Ip2regionSearcher search(String ip) throws IOException {
        return search(ip, ALGORITHM.BTREE_SEARCH);
    }

    public synchronized Ip2regionSearcher search(String ip, ALGORITHM algorithm) throws IOException {
        DataBlock dataBlock = null;
        switch (algorithm) {
            case BTREE_SEARCH:
                dataBlock = this.dbSearcher.btreeSearch(ip);
                break;
            case BINARY_SEARCH:
                dataBlock = this.dbSearcher.binarySearch(ip);
                break;
            case MEMORY_SEARCH:
                dataBlock = this.dbSearcher.memorySearch(ip);
                break;
        }
        if (dataBlock != null) {
            threadLocal.set(dataBlock.getRegion());
        }
        return this;
    }

    @Override
    public String toString() {
        String d = threadLocal.get();
        if (StringUtils.isEmpty(d)) {
            return "";
        }
        return d;
    }

    public String getCountry() {
        return getByIdx(0);
    }

    public String getRegion() {
        return getByIdx(1);
    }

    public String getProvince() {
        return getByIdx(2);
    }

    public String getCity() {
        return getByIdx(3);
    }

    public String getISP() {
        return getByIdx(4);
    }

    private String getByIdx(int i) {
        String d = threadLocal.get();
        if (StringUtils.isEmpty(d)) {
            return "";
        }
        List<String> list = Arrays.asList(StringUtils.delimitedListToStringArray(d, "|"));
        return list.get(i);
    }

    @Override
    public void destroy() throws Exception {
        this.dbSearcher.close();
        this.dbSearcher = null;
    }
}
